<?php

namespace DesignPatterns;

/**
 * Class Beverage 饮料抽象类
 * @package DesignPatterns
 *
 */
/**
 * Class Beverage
 * @package DesignPatterns
 */
abstract class Beverage
{
    /**
     * getDescribe 获取描述
     * @return string
     */
    abstract public function getDescribe(): string;
    
    /**
     * calcCost 计算价格
     * @return float
     */
    abstract public function calcCost(): float;
}

/**
 * 调料装饰器基类
 * Class CondimentDecorator
 * @package DesignPatterns
 */
abstract class CondimentDecorator extends Beverage
{
    /**
     * 被装饰的饮料实现类
     * @var Beverage
     */
    protected $_beverage;
    
    /**
     * CondimentDecorator constructor.
     * @param Beverage $_beverage
     */
    public function __construct(Beverage $_beverage)
    {
        $this->_beverage = $_beverage;
    }
}

/**
 * 咖啡
 * Class Coffee
 * @package DesignPatterns
 */
class Coffee extends Beverage
{
    
    /**
     * getDescribe 获取描述
     * @return string
     */
    public function getDescribe(): string
    {
        return '咖啡';
    }
    
    /**
     * calcCost 计算价格
     * @return float
     */
    public function calcCost(): float
    {
        return 15;
    }
}

/**
 * 摩卡咖啡
 * Class Mocha
 * @package DesignPatterns
 */
class Mocha extends Beverage
{
    
    /**
     * getDescribe 获取描述
     * @return string
     */
    public function getDescribe(): string
    {
        return '摩卡咖啡';
    }
    
    /**
     * calcCost 计算价格
     * @return float
     */
    public function calcCost(): float
    {
        return 18;
    }
}

/**
 * 白砂糖调料装饰器
 * Class Sugar
 * @package DesignPatterns
 */
class Sugar extends CondimentDecorator
{
    /**
     * getDescribe 获取描述
     * @return string
     */
    public function getDescribe(): string
    {
        return $this->_beverage->getDescribe() . ',白砂糖';
    }
    
    /**
     * calcCost 计算价格
     * @return float
     */
    public function calcCost(): float
    {
        return $this->_beverage->calcCost() + 1.5;
    }
}

/**
 * 牛奶调料装饰器
 * Class Milk
 * @package DesignPatterns
 */
class Milk extends CondimentDecorator
{
    
    /**
     * getDescribe 获取描述
     * @return string
     */
    public function getDescribe(): string
    {
        return $this->_beverage->getDescribe() . ',牛奶';
    }
    
    /**
     * calcCost 计算价格
     * @return float
     */
    public function calcCost(): float
    {
        return $this->_beverage->calcCost() + 2;
    }
}

/**
 * 牛奶调料装饰器
 * Class Milk
 * @package DesignPatterns
 */
class Foam extends CondimentDecorator
{
    
    /**
     * getDescribe 获取描述
     * @return string
     */
    public function getDescribe(): string
    {
        return $this->_beverage->getDescribe() . ',奶泡';
    }
    
    /**
     * calcCost 计算价格
     * @return float
     */
    public function calcCost(): float
    {
        return $this->_beverage->calcCost() + 2.1;
    }
}

// 顾客点了一杯咖啡+奶泡
$beverage = new Coffee();
$beverage = new Foam($beverage);
echo $beverage->getDescribe();
echo '  总价:' . $beverage->calcCost();
echo PHP_EOL;

// 顾客点了一杯摩卡咖啡+奶泡
$beverage = new Mocha();
$beverage = new Foam($beverage);
echo $beverage->getDescribe();
echo '  总价:' . $beverage->calcCost();
echo PHP_EOL;

// 顾客点了一杯咖啡+糖
$beverage = new Coffee();
$beverage = new Sugar($beverage);
echo $beverage->getDescribe();
echo '  总价:' . $beverage->calcCost();
echo PHP_EOL;

// 顾客点了一杯咖啡+牛奶
$beverage = new Coffee();
$beverage = new Milk($beverage);
echo $beverage->getDescribe();
echo '  总价:' . $beverage->calcCost();
echo PHP_EOL;

// 顾客点了一杯咖啡+牛奶+白糖
$beverage = new Coffee();
$beverage = new Milk($beverage);
$beverage = new Sugar($beverage);
echo $beverage->getDescribe();
echo '  总价:' . $beverage->calcCost();
echo PHP_EOL;
